﻿#pragma once

#include "../lang/lang.hh"
#include "../util/box_std_allocator.hh"

#include <memory>
#include <cstdio>
#include <type_traits>
#include <unordered_map>

namespace kratos {
namespace service {
class ServiceBox;
}
} // namespace kratos

namespace kratos {
namespace lang {

/**
 * 语言ID.
 */
enum class LangID : std::uint64_t {
  LANG_BOX_PARSE_ARGUMENT_FAIL = 1,
  LANG_BOX_LOAD_CONFIG_FAIL, // %S
  LANG_BOX_OS_REGISTER_FAIL,
  LANG_BOX_START_NETWORK_FAIL,
  LANG_BOX_GETTING_NECESSARY_SERVICE,
  LANG_BOX_GOT_NECESSARY_SERVICE,
  LANG_BOX_STARTED,
  LANG_BOX_START_FAILURE,
  LANG_BOX_PARSE_CONFIG_FAIL,  // %s
  LANG_BOX_CREATE_FINDER_FAIL, // %s
  LANG_BOX_START_FINDER_FAIL,  // %s %s
  LANG_BOX_START_CLEANUP,
  LANG_BOX_STOPPED,
  LANG_BOX_SERVICE_ADDRESS_INCORRECT, // %s %s
  LANG_BOX_CREATE_LOGGER_FAIL,
  LANG_BOX_START_LOGGER_FAIL,           // %s %s
  LANG_BOX_LOCAL_SERVICE_DIR_NOT_FOUND, // %s
  LANG_BOX_START_REMOTE_SERVICE_FAIL,
  LANG_BOX_LOAD_LOCAL_SERVICE_FAIL,           // %s %s %s
  LANG_BOX_LOAD_LOCAL_SERVICE_DIR_NOT_FOUND,  // %s %s %s
  LANG_BOX_LOAD_LOCAL_SERVICE_SUCCESS,        // %s
  LANG_BOX_START_LISTENER_FAIL,               // %s
  LANG_OS_RELOAD_CONFIG_FAIL,                 // %s %s
  LANG_OS_RELOAD_CONFIG_SUCCESS,              // %s
  LANG_HTTP_CONNECT_REMOTE_REPO_FAIL,         // %s
  LANG_HTTP_PARSE_REMOTE_VERSION_CONFIG_FAIL, // %s
  LANG_HTTP_CREATE_LOCAL_FILE_FAIL,           // %s %s
  LANG_HTTP_CREATE_LOCAL_DIR_FAIL,            // %s
  LANG_HTTP_DOWNLOAD_REMOTE_BUNDLE_FAIL,      // %s
  LANG_HTTP_UPDATE_REMOTE_SERVICE_EXCEPT,     // %s
  LANG_HTTP_UPDATE_SERVICE_FAIL,              // %s
  LANG_HTTP_CREATE_LOCAL_VERSION_FILE_FAIL,   // %s
  LANG_HTTP_CREATE_CONNECTOR_FAIL,            // %s %d
  LANG_HTTP_CREATE_LISTENER_FAIL,             // %s %d
  LANG_SERVICE_CONTEXT_REQUEST_SHUTDOWN,
  LANG_CORO_RUNNER_EXCEPTION,                 // %s
  LANG_COMMAND_EXCEPTION,                     // %s %s  
  LANG_STARTUP_INFO_LISTENER, // %s
  LANG_STARTUP_INFO_FINDER, // %s %s
  LANG_STARTUP_INFO_NECESSARY_SERVICE, // %s
  LANG_STARTUP_INFO_REGISTER_SERVICE, // %s %s
  LANG_STARTUP_INFO_UNREGISTER_SERVICE, // %s
  LANG_STARTUP_INFO_COROUTINE, // %s
  LANG_STARTUP_INFO_LOCAL_SERVICE_DIR, // %s
  LANG_STARTUP_INFO_LOCAL_SERVICE, // %s
  LANG_STARTUP_INFO_OPEN_REMOTE_UPDATE, // %s
  LANG_STARTUP_INFO_REMOTE_REPO_DIR, // %s
  LANG_STARTUP_INFO_REMOTE_VERSION_API, // %s
  LANG_STARTUP_INFO_REMOTE_LATEST_VRSION_API, // %s
  LANG_STARTUP_INFO_REMOTE_UPDATE_CHECK_INTVAL, // %s
  LANG_STARTUP_INFO_DAEMON, // %s
  LANG_STARTUP_INFO_COMMAND_MANAGER, // %s
  LANG_STARTUP_INFO_COMMAND_MANAGER_ADDRESS, // %s
  LANG_COMMAND_INFO,  // %s
  LANG_RELOAD_INFO, // %s
  LANG_STARTUP_EXCEPTION, // %s
  LANG_RUNTIME_EXCEPTION, // %s %s
  LANG_START_LISTENER_FAIL, // %s
  LANG_CONFIG_ERROR, // %s
  LANG_UNEXPECTED_EXCEPTION, // %s %s %s
  LANG_UNEXPECTED_ERROR, // %s %s
  LANG_PROXY_CONFIG_NOT_FOUND,
  LANG_START_AS_PROXY,
  LANG_PROXY_SEED_NOT_FOUND,
  LANG_REGISTER_UUID_SERVICE_FAILED, // %s %s
  LANG_PROXY_VIRTUAL_ID_EXHAUSTED,
  LANG_PROXY_ADD_OUTSIDE_TRANSPORT_FAILED,
  LANG_PROXY_FIND_SERVICE_TIMEOUT, // %s
  LANG_PROXY_INVALID_HEADER, // %s
  LANG_PROXY_NOT_FOUND_SERVICE_FOR_RETURN,
  LANG_PROXY_CONFIG_ERROR, // %s
  LANG_PROXY_LISTENER_INFO, // %s
  LANG_REDIS_INVALID_ARGUMENT, // %s
  LANG_REDIS_CONNECT_FAIL, // %s
  LANG_REDIS_EXEC_FAIL, // %s
  LANG_HOST_CONNECT_INFO, // %s %s %d
  LANG_HOST_DISCONNECT_INFO, // %s %s %d
  LANG_TIMER_HANDLE_EXCEPTION, // %s
  LANG_CSV_REBUILD_INDEX_FAIL, // %s
  LANG_CONFIG_TYPE_ERROR, // %s
  LANG_CONFIG_MISSING_ATTR, // %s
  LANG_ASSERTION_FAIL, // %s %s %d %s
  LANG_SERVICE_ASSERTION_FAIL, // %s %s %d %s
  LANG_CONSOLE_CONFIG_ERROR,
  LANG_LUA_ERROR, // %s
  LANG_ANOTHER_INSTANCE, 
};

/**
 * 语言包实现.
 */
class LangImpl : public Lang {
  std::string file_path_; ///< 配置文件路径
  std::string default_language_{"cn-simple"}; ///< 默认语言
  std::string language_; ///< 当前语言
  using LangMap = kratos::service::PoolUnorederedMap<std::uint64_t, LangInfo>;
  LangMap default_lang_map_; ///< 默认语言表
  LangMap lang_map_; ///< 当前语言表

public:
  /**
   * 构造
   * \param internal 是否是内部使用
   */
  LangImpl(bool internal = true);
  /**
   * 析构
   */
  virtual ~LangImpl();
  virtual auto load_default(const std::string &default_lang_path)
      -> bool override;
  virtual auto load_default(const std::string& name, const DefaultMap &)
      -> void override;
  virtual auto get_language() -> const std::string & override;
  virtual auto get_lang(LangID id) noexcept -> const std::string & override;
  virtual auto load(const std::string &file_path) -> bool override;
  virtual auto reload() -> bool override;
  
  template <typename...ARGS>
  auto printf_lang(LangID lang_id, ARGS...args) -> const char* {
    constexpr static int snprintf_buffer_length = 1024 * 8;
    thread_local static char snprintf_buffer[snprintf_buffer_length + 1] = {0};
    auto it = lang_map_.find(std::underlying_type<LangID>::type(lang_id));
    if (it == lang_map_.end()) {
        return "";
    }
    const auto& lang_info = it->second;
    auto print_size = std::snprintf(
        snprintf_buffer,
        snprintf_buffer_length,
        lang_info.line.c_str(),
        args...);
    if (print_size <= 0) {
        return "";
    }
    snprintf_buffer[snprintf_buffer_length] = 0;
    return snprintf_buffer;
  }
};

} // namespace lang
} // namespace kratos
